package com.spring.schedule_system.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.date.StopWatch;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.spring.schedule_system.dengxiaojiao.util.*;
import com.sun.org.apache.bcel.internal.generic.NEW;
import com.szlanyou.cloud.uid.utils.LyIdUtils;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import static java.lang.String.format;

/**
 *
 * @author        ly-dengxiaojiao
 * @date          2023-06-05
 */
@Service
public class CarDeliveryAppService {
    private static final Logger log = LoggerFactory.getLogger(CarDeliveryAppService.class);

    private static StringRedisTemplate redisTemplate;
    @Autowired
    VenBuDeliveryOrderSaveManager venBuDeliveryOrderSaveManager;

    //保存交车
    @GlobalTransactional(rollbackFor = Exception.class)//声明开启分布式事务
    public OptResult venBuDeliveryOrderSave( Map<String, Object> map) {
        String allDeliveryKey = "ALL_DELIVERY_QTY";
        String carDeliveryKey = "BASE_" + map.get("orgCarBrandCode") + "_" + map.get("baseSeriesId");
        String dlrDeliveryKey = "DLR_DELIVERY_QTY_" + map.get("parentDlrId");
//        VenBuDeliveryOrderAndPreDeliveryOrderSaveDomainIn info = LyObjectUtil.convertToByJSON(venBuDeliveryOrderAndPreDeliveryOrderSaveRequest, VenBuDeliveryOrderAndPreDeliveryOrderSaveDomainIn.class);
        try {
            String s = LocalDateTimeUtil.formatNormal(LocalDateTime.now());
            map.put("isSuccess", "0");

            //<editor-fold desc="数据校验">
            LocalDateTimeUtil.formatNormal(LocalDateTime.now());
            if (StringUtils.isEmpty("1")) {

            }

            //</editor-fold>


            //<editor-fold desc="本店交车">
            StopWatch sw = new StopWatch("交车耗时");
            sw.start();
            OptResult optResult = new OptResult();

            optResult = this.saveDeliveryOrder(map);
            sw.stop();
            System.out.println("整个交车try阶段执行时间程序执行时间为：" + sw.getTotalTimeSeconds() + "秒");

            //</editor-fold>



            venBuDeliveryOrderSaveManager.deliveryPrepare(map, null);


            return optResult;

        } catch (Exception e) {
            if ("1".equals(map.get("isSuccess"))) {
                //清除交车中缓存数量
                redisTemplate.opsForValue().increment(allDeliveryKey, -1);
                redisTemplate.opsForValue().increment(carDeliveryKey, -1);
                redisTemplate.opsForValue().increment(dlrDeliveryKey, -1);
//                TransactionRedisUtil.StringOps.incrBy(carDeliveryKey, -1);
//                TransactionRedisUtil.StringOps.incrBy(dlrDeliveryKey, -1);
            }
//            throw BizException.newBizException(CommonError.LOGIC_ERROR.getErrorCode(), e.getMessage(), e);
            throw new RuntimeException(e);

        }
    }

    public OptResult saveDeliveryOrder(Map<String,Object> map ) {
        List<CompletableFuture<OptResult>> confirmFutureList = new ArrayList<>();

        //<editor-fold desc="后台校验">

        //<editor-fold desc="系统参数配置统一查询">
        StopWatch sw1 = new StopWatch("交车耗时");
        sw1.start();
        Map<String, Object> sysParaConfigLocalOuts = new HashMap<>();
        Map<String, Object> lookupValueDtos = new HashMap<>();
        //涉及到用专营店获取数据的开关都要取ORG_CAR_BRAND_CODE，根据TOKEN的MAIN_ORG_CAR_BRAND_CODE,否则就根据单据的ORG_CAR_BRAND_CODE去获取
        Map<String, Object> sysParaConfigLocal1 = new HashMap<>();
       Map<String, Object> sysParaConfigLocal2 = new HashMap<>();
       Map<String, Object> sysParaConfigLocal3 = new HashMap<>();
       Map<String, Object> sysParaConfigLocal5 = new HashMap<>();
       Map<String, Object> sysParaConfigLocal6 = new HashMap<>();
       Map<String, Object> sysParaConfigLocal8 = new HashMap<>();
       Map<String, Object> sysParaConfigLocal9 = new HashMap<>();
       Map<String, Object> lookupValue1 = new HashMap<>();
       Map<String, Object> lookupValue3 = new HashMap<>();
       Map<String, Object> lookupValue4 = new HashMap<>();
        //查询大客户零售业绩开关 SYS_VE_VIP_FEAT_00001
        String pramar = "SYS_VE_PV_VIP_PREDELIVERY,SYS_VE_PV_G1_REPORT,SYS_VE_PV_G2_REPORT,SYS_VE_VIP_FEAT_00001,SYS_VE_PV_00135,SYS_VE_PV_00801,SYS_VE_PV_00803,SYS_VE_PV_00802";
//        ListResult<SysParaConfigLocalOut> predelivery = this.veDbTargetSwitchQueryBatch(pramar, info.getOrgCarBrandCode());//前端传入的orgCarBrandCode是token中的mainOrgCarBrandCode
        String lookupTypeCode = "VE0804,VE0684,VE0654";
//        ListResult<LookupValueDto> lookupValueDtoListResult = this.mdsnLookupValueFindByPage(lookupTypeCode, null);
        if (true) {
            //大客户业绩交车开关
//            sysParaConfigLocal1 = predelivery.getRows().stream().filter(i -> i.getParameterCode().equals("SYS_VE_PV_VIP_PREDELIVERY") && "1".equals(i.getParameterValue())).findFirst().orElse(null);
//            //G1大客户报备校验开关
//            sysParaConfigLocal2 = predelivery.getRows().stream().filter(i -> i.getParameterCode().equals("SYS_VE_PV_G1_REPORT") && "1".equals(i.getParameterValue())).findFirst().orElse(null);
//            //G2大客户报备校验开关
//            sysParaConfigLocal3 = predelivery.getRows().stream().filter(i -> i.getParameterCode().equals("SYS_VE_PV_G2_REPORT") && "1".equals(i.getParameterValue())).findFirst().orElse(null);
//            //大客户零售业绩开关
//            sysParaConfigLocal5 = predelivery.getRows().stream().filter(i -> i.getParameterCode().equals("SYS_VE_VIP_FEAT_00001") && "1".equals(i.getParameterValue())).findFirst().orElse(null);
//            //交车提醒总开关
//            sysParaConfigLocal6 = predelivery.getRows().stream().filter(i -> i.getParameterCode().equals("SYS_VE_PV_00135") && "1".equals(i.getParameterValue())).findFirst().orElse(null);
//            //全车系交车每日每月上限
//            sysParaConfigLocal8 = predelivery.getRows().stream().filter(i -> i.getParameterCode().equals("SYS_VE_PV_00803") && "VE".equals(i.getBusinessModle()) && "1".equals(i.getParameterValue())).findFirst().orElse(null);
//            //基准车系交车上限提示消息开关
//            sysParaConfigLocal9 = predelivery.getRows().stream().filter(i -> i.getParameterCode().equals("SYS_VE_PV_00802") && saleContractData.getOrgCarBrandCode().equals(i.getCarBrandCode())).findFirst().orElse(null);

        }
        sysParaConfigLocalOuts.put("sysParaConfigLocal1", sysParaConfigLocal1);
        sysParaConfigLocalOuts.put("sysParaConfigLocal2", sysParaConfigLocal2);
        sysParaConfigLocalOuts.put("sysParaConfigLocal3", sysParaConfigLocal3);
        sysParaConfigLocalOuts.put("sysParaConfigLocal5", sysParaConfigLocal5);
        sysParaConfigLocalOuts.put("sysParaConfigLocal6", sysParaConfigLocal6);
        sysParaConfigLocalOuts.put("sysParaConfigLocal8", sysParaConfigLocal8);
        sysParaConfigLocalOuts.put("sysParaConfigLocal9", sysParaConfigLocal9);
        lookupValueDtos.put("lookupValue1", lookupValue1);
        lookupValueDtos.put("lookupValue3", lookupValue3);
        lookupValueDtos.put("lookupValue4", lookupValue4);
        sw1.stop();
        System.out.println("系统参数配置统一查询程序执行时间为：" + sw1.getTotalTimeSeconds() + "秒");
        //</editor-fold>

        //<editor-fold desc="交车时间段判断">
        //工具方式调用
        CompletableFuture<OptResult> deliveryTimeResult = TransactionAsyncUtil
                .supplyAsync((Supplier<OptResult>) () -> {
                    StopWatch sw2 = new StopWatch("交车耗时");
                    sw2.start();
                    sw2.stop();
                    System.out.println("交车时间段判断程序执行时间为：" + sw2.getTotalTimeSeconds() + "秒");
                    return LyOptResultUtil.success("允许交车");

                });
        confirmFutureList.add(deliveryTimeResult);

        CompletableFuture.supplyAsync((Supplier<OptResult>) () -> {
            StopWatch sw2 = new StopWatch("交车耗时");
            sw2.start();
            sw2.stop();
            System.out.println("交车时间段判断程序执行时间为：" + sw2.getTotalTimeSeconds() + "秒");
            return LyOptResultUtil.success("允许交车");

        });
        //</editor-fold>

        //<editor-fold desc="业绩交车需要发票效验">
            CompletableFuture<OptResult> preInvoiceCheckResult = TransactionAsyncUtil
                    .supplyAsync((Supplier<OptResult>) () -> {
                        StopWatch sw3 = new StopWatch("交车耗时");
                        sw3.start();


                        sw3.stop();
                        System.out.println("业绩交车需要发票效验程序执行时间为：" + sw3.getTotalTimeSeconds() + "秒");
                        return LyOptResultUtil.success("业绩交车需要发票校验通过");
                    });
            confirmFutureList.add(preInvoiceCheckResult);

        //</editor-fold>

        //<editor-fold desc="大客户是否业绩交车">
        //交车时校验客户订单类型，做相应的交车弹框提醒

        //</editor-fold>

        //<editor-fold desc="系统参数配置统一查询">
        StopWatch sw7 = new StopWatch("交车耗时");
        sw7.start();

        //</editor-fold>

        //<editor-fold desc="业绩交车转交车作业超过30天的车辆，交车作业功能关闭">


        //</editor-fold>

        //<editor-fold desc="启辰品牌 发送短信">


        //</editor-fold>

        //<editor-fold desc="交车更新客户订单可视化数据">
        CompletableFuture<OptResult> visualCheckResult = TransactionAsyncUtil
                .supplyAsync((Supplier<OptResult>) () -> {
                    StopWatch sw11 = new StopWatch("交车耗时");
                    sw11.start();

                    sw11.stop();
                    System.out.println("交车更新客户订单可视化数据程序执行时间为：" + sw11.getTotalTimeSeconds() + "秒");
                    return LyOptResultUtil.success("更新可视化数据成功");
                });
        confirmFutureList.add(visualCheckResult);
        //</editor-fold>

        //预留交车数量
        redisTemplate.opsForValue().increment("allDeliveryKey", -1);
        long yuliuAllCount = redisTemplate.opsForValue().increment("allDeliveryKey", -1);
        long yuliuCarCount = redisTemplate.opsForValue().increment("carDeliveryKey", -1);
        long yuliuDlrCount = redisTemplate.opsForValue().increment("dlrDeliveryKey", -1);

        map.put("isSuccess", "1");

        //<editor-fold desc="交车上限限制">

        //</editor-fold>

        //<editor-fold desc="判断是否收全款，是否开票">

        //根据新需求，4，7两类单据不检查开票信息，但开票日期必填。取交车时间代替

        //</editor-fold>

        //<editor-fold desc="判断基准车系交车上限是否达到上限">

        //</editor-fold>

        //<editor-fold desc="交车车型限制(限制某款车型不能交车)">

        //</editor-fold>

        //<editor-fold desc="车辆是否已有交车业绩">

        //</editor-fold>


        //</editor-fold>

        //<editor-fold desc="客户保存">


        //</editor-fold>

        //<editor-fold desc="单据、交车单、业绩保存">

        //<editor-fold desc="订单信息是否已被更新">


        //</editor-fold>

        //<editor-fold desc="1、更新销售订单 销售订单明细 销售订单明细扩展表数据">
        StopWatch sw18 = new StopWatch("交车耗时");
        sw18.start();

        sw18.stop();
        System.out.println("更新销售订单程序执行时间为：" + sw18.getTotalTimeSeconds() + "秒");
        //</editor-fold>

        //<editor-fold desc="2、新增订单异动日志 ">


        //</editor-fold>

        //<editor-fold desc="3、保存交车单/交车检查项">

        //<editor-fold desc="客户保存线程执行完毕 再执行交车保存">


        //</editor-fold>

        //保存交车检查项

        //2.2.1、已有交车单 更新交车单

        //2.2.2、不存在交车单 新增交车单

        //</editor-fold>

        //<editor-fold desc="4、新增交车业绩表">
                Map<String, String> checkParamMap = MapUtil.<String, String>builder()
                        .put("featId", "业绩明细ID")
                        .put("dlrId", "交车专营店ID")
                        .put("deliveryDate", "交车日期")
                        .put("featType", "业绩类型")
                        .put("delType", "交车类型")
                        .put("caUserId", "销售顾问ID")
                        .put("caEmpName", "销售顾问名称")
                        .put("carConfigId", "车型配置ID")
                        .put("carColorId", "车身颜色ID")
                        .put("carIncolorId", "内饰颜色ID")
                        .put("vin", "VIN码")
                        .put("deliveryQty", "交车数")
                        .put("modifier", "最后更新人员")
                        .put("creator", "创建人")
                        .put("modifyName", "最后更新人员姓名")
                        .put("createdName", "创建人姓名")
                        .put("lastUpdatedDate", "最后更新时间")
                        .put("updateControlId", "并发控制字段")
                        .put("orgCarBrandCode", "组织品牌编码")
                        .put("carBrandCode", "品牌编码")
                        .put("carBrandCn", "品牌名称")
                        .build();
                LocalCheckParamUtil.checkObjReqParams(map, checkParamMap, "新增交车业绩");


        //</editor-fold>

        //<editor-fold desc="5、更新PV大客户订单">
        //代PV大客户交车

        //</editor-fold>

        //</editor-fold>

        //<editor-fold desc="车辆保存">

        //<editor-fold desc="1、新增/更新销售车">

        //</editor-fold>

        //<editor-fold desc="2、更新主机厂/专营店库存冷热表信息 3、新增交车车籍异动 4、更新服务车型">


        //</editor-fold>

        //<editor-fold desc="4、正式交车时，更新试乘试驾车状态">


        //</editor-fold>

        //</editor-fold>

        //<editor-fold desc="销售出库逻辑">
        //销售出库时间为空的情况下说明没有出库，新增出库单、出库单明细

        //</editor-fold>


        //处理多线程执行结果
        if (confirmFutureList.size() > 0) {
            CompletableFuture<OptResult>[] confirmCompletableFutures = confirmFutureList.toArray
                    (new CompletableFuture[confirmFutureList.size()]);
            CompletableFuture.allOf(confirmCompletableFutures);//保证所有线程执行完毕
            try {
                for (CompletableFuture<OptResult> future : confirmCompletableFutures) {
                    OptResult checkResult = future.get();
                    if (!"1".equals(checkResult.getResult())) {
                        throw BizException.newBizException(checkResult.getResult(), checkResult.getMsg());
                    }
                }
            } catch (Exception e) {
                //清除交车数量缓存 2024-02-23
//            	this.ClearMapDeliveryQty(venBuSaleOrderD.getSaleOrderDId() , info.getParentDlrId(), saleContractData.getBaseSeriesId());
                log.error("venBuDeliveryOrderSave交车失败：", e);
                Throwable cause = e.getCause();
                if (cause instanceof BizException) {
                    // 如果异常已经是 BizException 类型，则直接返回
                    throw (BizException) cause;
                } else {
                    // 否则，将异常转换为 BizException 类型并返回
                    throw BizException.newBizException("111", e.getMessage(), cause);
                }
            }
        }
        String title = "";
        if ("1".equals(map.get("deliveryType"))) {
            title = "交付确认";
        } else {
            title = "业绩交车";
        }


        //<editor-fold desc="交付确认订单更新状态回写业务表 nev不同步订单信息到pz1a">


        //</editor-fold>

        //<editor-fold desc="交付确认,选择五年套餐赠送接口调用">

        //</editor-fold>

        //<editor-fold desc="交付确认,交车活动行为触发(大客户不触发)">
        //交车时，同步VIN给活动中心用于取送车发券 剔除大客户（直销大客户、专营店大客户、待交车大客户）


        //</editor-fold>

        //<editor-fold desc="上传交车到中台">


        //</editor-fold>

        //<editor-fold desc="交车确认场景(电池追溯)">

        //</editor-fold>

        //<editor-fold desc="售后调用">


        //</editor-fold>

        //<editor-fold desc="合同正式交车积分异动上传">


        //</editor-fold>

        //<editor-fold desc="交车信息发送给C端/零售中心">
        //NEV-10716 只发送C端saleType='1'来的大定信息


        //</editor-fold>

        //<editor-fold desc="已交车调用首页计算后台">


        //</editor-fold>

        //<editor-fold desc="交车成功需要把交付专员的跟进量回退加1，订单状态回传售后、交车修改合同状态为线下合同">

        //</editor-fold>



        return LyOptResultUtil.success(title + "成功");

    }


}


